package jus.aor.mobilagent.kernel;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AgentServer implements Runnable{
	/** liste de services */
	/** liste de services */
	protected Map<String,_Service<?>> services = new HashMap<String,_Service<?>>();
	protected int port;
	protected ServerSocket socket=null;
	protected String name;
	protected _Agent ag ;
	ClassLoader classLoader;
	public  Logger logger;
	public AgentServer (int port, String name, ClassLoader classLoader, Logger logger ){
		this.port = port;
		this.name=name;
		this.classLoader = classLoader;
		this.logger = logger;
		try {
			socket = new ServerSocket(port);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void addService(String name,_Service<?> service){
		services.put(name, service);
	}
	public _Service<?> getService(String name){
				return services.get(name);
	}
	
	public void run(){ 
		while (true){
			try {
				BAMLoader loader = new BAMLoader(classLoader);
				Socket s = socket.accept();
				logger.log(Level.FINE,"Reception d'un agent");
				ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
				Jar jar = (Jar)ois.readObject();
				loader.integrateCode(jar);
				AgentInputStream ais = new AgentInputStream(s.getInputStream(), loader);
				ag = (_Agent) ais.readObject();
				ag.init(this,name);				
				ag.addLoader(loader);
				runAgent(ag);
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}	
		}	
	}
	public void runAgent(_Agent a){
		a.run();
	}
	
	public URI site() throws URISyntaxException{
		return new URI(name);
	}
	
	public String toString(){
		return name;	
	}

	public void send(URI server, BAMLoader l, _Agent ag) { 
		Socket r;
		ObjectOutputStream out;
		try {
			logger.log(Level.FINE,"Envoi d'un agent");
			r = new Socket(server.getHost(),server.getPort());
			out = new ObjectOutputStream(r.getOutputStream());
			out.writeObject(l.extractCode());
			out = new ObjectOutputStream(r.getOutputStream());
			out.writeObject(ag);
			out.flush();
			out.close();	
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
